package com.apps.java.javanote02;

import java.util.ArrayList;
import java.util.List;

public class _22集合_泛型 {
    /**
     * 泛型
     * 	概述：泛型是JDK5中引入的特性，它提供了编译时类型安全检测机制，该机制允许在编译时检测到非法的类型；
     * 		它的本质是参数化类型，也就是说所操作的数据类型被指定为一个参数；
     * 		一提到参数，最熟悉的就是定义方法时有形参，然后调用此方法时传递实参。那么参数化类型怎么理解呢？
     * 		顾名思义，就是将类型由原来的具体的类型参数化，然后在使用/调用时传入具体的类型，这种参数类型可以用在类、方法和接口中，分别被称为泛型类、泛型方法、泛型接口。
     *
     * 	一、定义格式
     * 		1.<类型>：指定一种类型的格式，这里的类型可以看成是形参
     * 		2.<类型1,类型2,...>：指定多种类型的格式，多种类型之间用逗号隔开。这里的类型可以看成是形参
     * 		3.将来具体调用的时候给定的类型可以看成是实参，并且实参的类型只能是引用数据类型。
     *
     * 		泛型的好处：
     * 			1.将运行时期的问题提前到了编译时期
     * 			2.避免了强制类型转换
     *
     * 	二、泛型类
     * 		定义格式：
     * 			修饰符  class 类名<类型>{} ---> public class Generic<T>{}
     * 			此处T可以随便写为任意标识，常见的如T、E、K、V等形式的参数常用于表示泛型
     *
     * 	三、泛型接口
     * 		定义格式：
     * 			修饰符 interface 接口名<类型>{} ---> public interface Generic<T>{}
     *
     * 	四、类型通配符
     * 		为了表示各种泛型List的父类，可以使用类型通配符
     * 		格式：<?>
     * 			比方：List<?>表示元素类型未知的List，它的元素可以匹配任何类型
     *
     * 		注意事项：
     * 		1.为了表示各种泛型List的父类，可以使用类型通配符
     * 			1.类型通配符：<?>
     * 			2.List<?>：表示元素类型未知的List，他的元素可以匹配任何的类型
     * 			3.这种带通配符的List仅表示它是个各种泛型List的父类，并不能把元素添加到其中
     *
     * 		2.如果说我们不希望List<?>是任何泛型List的父类，只希望它代表某一类泛型List的父类，可以使用类型通配符的上限
     * 			1.类型通配符上限：<? extends 类型>
     * 			2.List<? extends Number>：它表示的类型是Number或者其子类型
     *
     * 		3.除了可以指定类型通配符的上限，也可以指定类型通配符的下限
     * 			1.类型通配符下限：<? super 类型>
     * 			2.List<? super Number>；它表示的类型是Number或者其父类型
     *
     * 		可变参数
     * 			可变参数又称参数个数可变，用作方法的形参出现，那么放啊参数个数就是可变的了
     * 			格式：修饰符 返回值类型 方法名（数据类型...变量名）{}
     * 			注意事项：
     * 				1.这里的变量其实是一个数组
     * 				2.如果一个方法有多个参数，包含可变参数，可变参数要放在最后
     * 			使用：
     * 				1.Arrays工具类中有一个静态方法：
     * 					public static <T> asList(T ...a)：返回由指定数组支持的固定大小的列表
     * 				2.List接口中有一个静态方法：
     * 					public static <E> List<E> of(E... elements)：返回包含任意数量元素的不可变列表
     * 				3.Set中有一个静态方法：
     * 					public static <E> Set<E> of(E... elements)：返回一个包含任意数量元素的不可变集合
     *
     *
     */

    public static void main(String[] args) {

        //类型通配符
        List<?> list = new ArrayList<Object>();
        List<?> list2 = new ArrayList<Number>();
        List<?> list3 = new ArrayList<Integer>();

        //类型通配符上限
        List<? extends Number> listtop1 = new ArrayList<Number>();
        List<? extends Number> listtop2 = new ArrayList<Integer>();
        //List<? extends Number> listtop3 = new ArrayList<Object>();//报错

        //类型通配符下限
        List<? super Number> listbot1 = new ArrayList<Object>();
        List<? super Number> listbot2 = new ArrayList<Number>();
        //List<? super Number> listbot3 = new ArrayList<Integer>();//报错


        //可变参数
        int[] a = {20,30,50,88,32,33};
        System.out.println(variableType(a));

        //多个参数的可变参数方法
        int b = 69;
        System.out.println(variableTypes(b, a));
    }

    //可变参数
    public static int variableType(int... a){
        int num = 0;
        for(int i : a){
            num += i;
        }
        return num;
    }

    //多个参数可变参数方法
    public static int variableTypes(int b,int...a){
        int num = 0;
        for(int i : a){
            num += i;
        }
        return num + b;
    }
}
